﻿#define _GNU_SOURCE
#include "Buffer.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/uio.h>
#include <string.h>
#include <unistd.h>
#include <strings.h>
#include <sys/socket.h>

struct Buffer* bufferInit(int size)
{
	struct Buffer* buffer = (struct Buffer*)malloc(sizeof(struct Buffer));
	if (buffer != NULL)
	{
		buffer->data = (char*)malloc(size);//获取缓存空间
		buffer->capacity = size;
		buffer->writePos = buffer->readPos = 0;
		memset(buffer->data, 0, size);
	}
	return buffer;
}
//销毁内存
void bufferDestroy(struct Buffer* buf)
{
	if (buf != NULL)
	{
		if (buf->data != NULL)
		{
			free(buf->data);
		}
	}
	free(buf);
}

void bufferExtendRoom(struct Buffer* buffer, int size)
{
	// 1. 内存够用 - 不需要扩容
	if (bufferWriteableSize(buffer) >= size)//连续可写容量
	{
		return;
	}
	// 2. 内存需要合并才够用 - 不需要扩容
	// 剩余的可写的内存 + 已读的内存 > size
	else if (buffer->readPos + bufferWriteableSize(buffer) >= size)//不连续写容量
	{
		// 得到未读的内存大小
		int readable = bufferReadableSize(buffer);
		// 移动内存
		memcpy(buffer->data, buffer->data + buffer->readPos, readable);
		// 更新位置
		buffer->readPos = 0;//更新读偏移量
		buffer->writePos = readable;//更新写偏移量
	}
	// 3. 内存不够用 - 扩容
	else
	{
		void* temp = realloc(buffer->data, buffer->capacity + size);
		if (temp == NULL)
		{
			return; // 失败了
		}
		memset(temp + buffer->capacity, 0, size);
		// 更新数据
		buffer->data = temp;
		buffer->capacity += size;
	}
}

int bufferWriteableSize(struct Buffer* buffer)
{
	return buffer->capacity - buffer->writePos;
}

int bufferReadableSize(struct Buffer* buffer)
{
	return buffer->writePos - buffer->readPos;
}

int bufferAppendData(struct Buffer* buffer, const char* data, int size)//数据写入buffer
{
	if (buffer == NULL || data == NULL || size <= 0)
	{
		return -1;
	}
	// 扩容（确保有空间写）
	bufferExtendRoom(buffer, size);//检测是否需要扩容，需要则扩，不需要直接返回
	// 数据拷贝
	memcpy(buffer->data + buffer->writePos, data, size);//写入可写空间
	buffer->writePos += size;//更新写数据偏移量
	return 0;
}

int bufferAppendString(struct Buffer* buffer, const char* data)
{
	int size = strlen(data);
	int ret = bufferAppendData(buffer, data, size);
	return ret;
}
//读取fd中的数据到buffer中
int bufferSocketRead(struct Buffer* buffer, int fd)
{
	// read/recv/readv
	struct iovec vec[2];//readv() 的参数 第一个元素不够存，继续往第二个存
	/*struct iovc{
	* void *iov_base;//starting address
	* size_t iov_len;//number of bytes to transfer
	* };
	*/
	// 初始化数组元素
	int writeable = bufferWriteableSize(buffer);
	vec[0].iov_base = buffer->data + buffer->writePos;//获得缓存写入位置
	vec[0].iov_len = writeable;//指定长度
	char* tmpbuf = (char*)malloc(40960);
	vec[1].iov_base = buffer->data + buffer->writePos;
	vec[1].iov_len = 40960;
	int result = readv(fd, vec, 2);//readv() 返回读取到的容量
	if (result == -1)
	{
		return -1;
	}
	else if (result <= writeable)//成功写入buffer中
	{
		buffer->writePos += result;//更新写入偏移量
	}
	else//没能直接写入buffer ，剩下的写入temp中，再将temp转存至buffer（扩容）
	{
		buffer->writePos = buffer->capacity;//更新写入偏移量（原buffer已写满）
		bufferAppendData(buffer, tmpbuf, result - writeable);//函数内检测到写不完（已写满），自行扩容，写入
	}
	free(tmpbuf);
	return result;//返回接收到的数据大小
}

char* bufferFindCRLF(struct Buffer* buffer)
{
	// strstr --> 大字符串中匹配子字符串(遇到\0结束) char *strstr(const char *haystack, const char *needle);
	// memmem --> 大数据块中匹配子数据块(需要指定数据块大小)
	// void *memmem(const void *haystack, size_t haystacklen,
	//      const void* needle, size_t needlelen);
	char* ptr = memmem(buffer->data + buffer->readPos, bufferReadableSize(buffer), "\r\n", 2);
	return ptr;
}

int bufferSendData(struct Buffer* buffer, int socket)
{
	// 判断有无数据
	int readable = bufferReadableSize(buffer);
	if (readable > 0)
	{
		int count = send(socket, buffer->data + buffer->readPos, readable, MSG_NOSIGNAL);
		if (count > 0)
		{
			buffer->readPos += count;
			usleep(1);
		}
		return count;
	}
	return 0;
}